# -*- coding: utf-8 -*-
"""
# @Time    : 2022/11/8 10:02
# @Author  : Youngson
# @File    : Day6
# @Software: PyCharm
# @Desc    : 
"""
import functools
import random
from collections import Counter
from copy import deepcopy


class Player():
    def __init__(self, name):
        self.name = name
        self.__cards = []

    def __repr__(self):
        return self.name

    @property
    def level(self):
        return self.__card_analysis()

    @property
    def cards(self):
        return self.__cards

    @cards.setter
    def cards(self, value):
        self.__cards.append(value)
        self.__cards.sort(key=lambda x: x.value)

    @property
    def card_values(self):
        return [card.value for card in self.__cards]

    @property
    def card_colors(self):
        return [card.symbol for card in self.__cards]

    @property
    def card_names(self):
        return [card.name for card in self.__cards]

    def __card_analysis(self):
        """分析牌型:
        6豹子：三张一样的牌，如3张6.大于其他任何牌型，同类型中3个A最大，3个2最小
        5顺金：又称同花顺，即3张同样花色的顺子， 如红桃 5、6、7。是花色一样的顺子，它比豹子小，但比其余的4种牌型都大。有的地方讲A23比QKA大，但常规来讲都是QKA最大，具体规则玩家可以事先商定。
        4金花：就是花色一样，但不是顺子的三张牌，比较时以最大的一张开始比起，如果最大的一个相同，就从第二个数字比起，以此类推。
        3顺子：又称拖拉机，花色不同，但是顺子，如红桃5、方片6、黑桃7，组成的顺子。是花色不同，三张连续的数字，切记它和【顺金】的差别，是花色不同的三个连续的数字。顺子比对子大，比单牌大，但是比花色一样的任何一种牌型都小。
        2对子：2张牌一样。对子就是有两张一样的牌，外加一张不同的牌，和豹子的区别就在于豹子是三张一样的而对子只有两张一样的。对子比单牌大，比顺子小，是倒数第二大的牌型。对子与对子之间的比较也是按照对子的大小来比较的。例如对K大于对Q，如果同是对Q，那么就比较第三张牌的大小。
        1单张：单张最大的是A。凡是没有起到以上5种类型的牌都是单牌，也就是最普通的牌。比较规则是：玩家与玩家比较时先比较最大的那一张，最大的那一张一样的话就比较第二张，以此类推。
        0特殊：不同花色的235
        """
        level = None
        if len(self.cards) < 3: return level
        set_value_len = len(set(self.card_values))
        set_color_len = len(set(self.card_colors))
        if set_value_len == 1:  # 豹子
            level = (6, sum(self.card_values), '豹子', self.cards)
        elif set_value_len == 2:  # 对子
            card_values = {v: k for k, v in Counter(self.card_values).items()}
            level = (2, (card_values[2], card_values[1]), '对子', self.cards)
        elif set_value_len == 3:
            # 暂不考虑A,2,3的情况
            continuous = []
            for i in range(len(self.card_values)):
                if not continuous:
                    continuous.append([self.card_values[i]])
                elif self.card_values[i - 1] + 1 == self.card_values[i]:
                    continuous[-1].append(self.card_values[i])
                else:
                    continuous.append([self.card_values[i]])
            is_continuous = True if len(continuous) == 1 else False
            # print(is_continuous, continuous)
            if set_color_len == 1:  # 顺金/金花
                if is_continuous:
                    level = (5, sum(self.card_values), '顺金', self.cards)
                else:
                    level = (4, sum(self.card_values), '金花', self.cards)
            else:  # 顺子/单张
                if is_continuous:  # 顺子
                    level = (3, sum(self.card_values), '顺子', self.cards)
                else:
                    level = (1, sum(self.card_values), '单张', self.cards)

        return level


class Card():
    def __init__(self, name, value, color):
        self.name = name
        self.value = value
        self.color = color
        self.__color_symbol = {"Spade": "♠", "Heart": "♡", "Diamond": "♢", "Club": "♣"}

    @property
    def symbol(self):
        return f"{self.__color_symbol.get(self.color, self.color)}"

    def __repr__(self):
        return f"[{self.__color_symbol.get(self.color, self.color)}{self.name}]"


class Poker():
    def __init__(self, player_names=None):
        self.cards = []
        self.players = []
        self.__player_names = player_names

        self.init()

    def init(self):
        self.cards = self.generate_card()
        self.players = self.generate_play(self.__player_names)

    @staticmethod
    def generate_play(names=None):
        """生成玩家列表"""
        player_names = names or ['Tom', 'Jack', 'Alex']
        __players = [Player(i) for i in player_names]

        return __players

    @staticmethod
    def generate_card():
        """生成扑克牌
        花色:黑桃 （Spade）、 红桃 （Heart）、 方块 （Diamond）、 梅花 （Club）
        :return:
        """
        values = [i for i in range(2, 15)]
        names = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
        colors = ["Spade", "Heart", "Diamond", "Club"]
        cards = [Card(names[i], values[i], color) for color in colors for i, name in enumerate(names)]

        return cards

    def shuffle_card(self):
        """洗牌"""
        # print('洗牌前', self.cards)
        random.shuffle(self.cards)
        # print('洗牌后', self.cards)

    def deal_card(self, round=3):
        """发牌"""
        for i in range(round):
            for player in self.players:
                if self.cards:
                    card = random.choice(self.cards)  # 洗牌过,可以使用self.cards.pop() 代替remove
                    player.cards = deepcopy(card)
                    self.cards.remove(card)
                    # print(player, '拿到一张', card)
                else:
                    print('牌已发完')
                # print('***第', i + 1, '轮发牌后', player.name, '手上的牌***', player.cards, '\n')

    def rank_player(self):
        def compare(a, b):
            """需要有三个返回值{-1， 0， 1}，当a<b时，返回值为-1，a=b时，返回值为0，a>b时，返回值为1."""
            # print(a.level, b.level)
            if a.level[0] != b.level[0]:
                return -1 if a.level[0] < b.level[0] else 1
            else:
                if a.level[1] < b.level[1]:
                    return -1
                elif a.level[1] > b.level[1]:
                    return 1
                else:
                    if a.level[0] == 2 and b.level[0] == 2:
                        if a.level[1][0] != b.level[1][0]:
                            return -1 if a.level[1][0] < b.level[1][0] else 1
                        else:
                            if a.level[1][1] < b.level[1][1]:
                                return -1
                            elif a.level[1][1] > b.level[1][1]:
                                return 1
                            else:
                                return 0
                    else:
                        return 0

        new_sort = sorted(self.players, key=functools.cmp_to_key(compare), reverse=True)
        return new_sort


if __name__ == '__main__':
    poker = Poker(player_names=['Alex', 'BlackGirl', 'Ian', 'Tom', 'Jack'])
    print("玩家:", poker.players)

    # print(poker.cards, '\n')
    poker.shuffle_card()
    print('洗牌后,待发牌:', poker.cards, '\n')

    poker.deal_card(3)
    for player in poker.players:
        # print(player.name, ':', len(player.cards), '张\n', player.card_colors, '\n', player.card_values)
        print(player.name, '手牌的牌型:', player.level[2], player.level[3])

    # 开牌
    new_players = poker.rank_player()
    # print(new_players, '\n')

    res = [f"{player.name}的{player.level[2]} {player.level[3]}" for player in new_players]
    print(' 大于 '.join(res), '\n')
    print(f'{new_players[0]}是本轮游戏的胜利者!!!')
